<?php
// +----------------------------------------------------------------------
// | KITEGO-Admin「开箱即用」「人人全栈」
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2024 https://www.kitego.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed KITEGO并不是自由软件，未经许可不能去掉KITEGO相关版权
// +----------------------------------------------------------------------
// | Author: KITEGO Team <bd@kitego.cn>
// +----------------------------------------------------------------------

namespace app\adminapi\services\setting;

use app\adminapi\validate\setting\SystemMenuValidate;
use app\dao\setting\SystemAdminDao;
use app\dao\setting\SystemMenuDao;
use app\dao\setting\SystemRoleDao;
use Exception;

class SystemMenuService
{
    private SystemMenuDao $dao;

    public function __construct(SystemMenuDao $dao)
    {
        $this->dao = $dao;
    }

    /**
     * 获取系统菜单
     * @throws Exception
     */
    public function getSystemMenu()
    {
        // 读取用户权限组
        $adminQuery = app()->make(SystemAdminDao::class)->find(request()->adminId);
        $roleIds = $adminQuery->role_id;
        if (empty($roleIds)) {
            exception('无菜单权限');
        }
        $roleIds = explode(',', $roleIds);

        // 读取权限对应菜单ids
        $roleWhere[] = ['id', 'in', $roleIds];
        $roleMenuIds = app()->make(SystemRoleDao::class)->getColumn($roleWhere, 'menu_ids', 'alias');
        if (empty($roleMenuIds)) {
            exception('无菜单权限');
        }

        // 超级管理员拥有全部权限
        if (!array_key_exists('super', $roleMenuIds)) {
            $roleMenuIdsNew = [];
            foreach ($roleMenuIds as $menuIds) {
                if (empty($roleMenuIdsNew)) {
                    $roleMenuIdsNew = explode(',', $menuIds);
                } else {
                    $roleMenuIdsNew = array_merge($roleMenuIdsNew, explode(',', $menuIds));
                }
            }
            $roleMenuIdsNew = array_unique($roleMenuIdsNew);

            $where[] = ['id', 'in', $roleMenuIdsNew];
        }

        // 读取该权限菜单
        $where[] = ['delete_flag', '=', 0];
        $field = [
            'id', 'pid', 'type', 'name', 'tag', 'icon', 'sort', 'path', 'component', 'auth', 'unique_auth',
            'show_flag', 'delete_flag', 'cache_flag', 'hidden_flag', 'hidden_breadcrumb_flag', 'is_keep_alive',
            'view_type'
        ];
        $menu = $this->dao->getMenuByRole($where, $field);
        if (empty($menu)) {
            exception('无有效菜单');
        }

        // 补全vue路由元信息
        foreach ($menu as &$v) {
            $v['meta'] = [
                'icon' => $v['icon'],
                'title' => $v['name'],
                'type' => $v['type'],
                'tag' => $v['tag'],
                'hidden' => $v['hidden_flag'],
                'hiddenBreadcrumb' => $v['hidden_breadcrumb_flag'],
                'isKeepAlive' => $v['is_keep_alive'],
                'viewType' => $v['view_type'],
            ];
        }

        // 生成子孙菜单
        $menu = make_tree($menu);

        // 取出权限唯一标识
        $permissions = find_array_value_by_key('unique_auth', $menu);

        // TODO 主页网格动态展示
        $dashboardGrid = ['welcome', 'ver', 'time', 'progress', 'echarts', 'about'];

        return success([
            'menu' => $menu,
            'permissions' => $permissions,
            'dashboardGrid' => $dashboardGrid
        ]);
    }

    /**
     * 菜单列表
     * @param array $param
     */
    public function listSystemMenu(array $param = [
        'name' => ''
    ])
    {
        try {
            // 读取菜单
            $where[] = ['delete_flag', '=', 0];

            // 关键词搜索
            if (!empty($param['name'])) {
                $where[] = ['name', '=', $param['name']];
            }
            $menu = $this->dao->getMenuByRole($where);

            if (!empty($menu)) {
                // 补全vue路由元信息
                foreach ($menu as &$v) {
                    $v['meta'] = [
                        'name' => $v['name'],
                        'icon' => $v['icon'],
                        'type' => $v['type'],
                        'active' => $v['active'],
                        'color' => $v['color'],
                        'fullpage' => $v['fullpage'],
                        'tag' => $v['tag'],
                        'hiddenFlag' => $v['hidden_flag'] . '' ?? '0',
                        'hiddenBreadcrumb' => $v['hidden_breadcrumb_flag'] . '' ?? '0',
                        'viewType' => $v['view_type'],
                    ];

                    $v['authList'][] = [
                        'is_verify' => is_numeric($v['is_verify']) ? $v['is_verify'] : '1',
                        'method' => $v['method'],
                        'auth' => $v['auth'],
                        'unique_auth' => $v['unique_auth']
                    ];

                    unset(
                        $v['icon'], $v['active'], $v['color'], $v['fullpage'], $v['tag'], $v['auth'], $v['method'],
                        $v['unique_auth'], $v['is_verify'], $v['hidden_flag'], $v['hidden_breadcrumb_flag'], $v['create_time'],
                        $v['update_time'], $v['delete_time'], $v['delete_flag'], $v['view_type']
                    );
                }

                // 生成子孙菜单
                $menu = make_tree($menu);
            }

            return success($menu);
        } catch (Exception $e) {
            return fail($e->getMessage());
        }
    }

    /**
     * 编辑菜单
     * @param array $param = ['path' => '', 'pid' => '', 'name' => '', 'type' => '']
     */
    public function editSystemMenu(array $param)
    {
        try {
            Validate(SystemMenuValidate::class)->scene('editSystemMenu')->check($param);

            // 非菜单、目录类型自动隐藏
            $hiddenFlag = !in_array($param['meta']['type'], ['menu', 'dir', 'link', 'iframe']) ? 1 : 0;

            // 菜单数据
            $updateData = [
                'pid' => $param['pid'],
                'name' => $param['name'],
                'sort' => $param['sort'] ?? 0,
                'path' => $param['path'] ?? '',
                'component' => $param['component'] ?? '',
                'icon' => $param['meta']['icon'] ?? '',
                'type' => $param['meta']['type'],
                'active' => $param['meta']['active'] ?? '',
                'color' => $param['meta']['color'] ?? '',
                'fullpage' => $param['meta']['fullpage'] ?? 0,
                'tag' => $param['meta']['tag'] ?? '',
                'auth' => $param['authList'][0]['auth'] ?? '',
                'is_verify' => $param['authList'][0]['isVerify'] ?? 1,
                'unique_auth' => $param['authList'][0]['uniqueAuth'] ?? '',
                'method' => $param['authList'][0]['method'] ?? '',
                'redirect' => $param['redirect'] ?? '',
                'show_flag' => $param['showFlag'] ?? 1,
                'cache_flag' => $param['cacheFlag'] ?? 1,
                'delete_flag' => $param['deleteFlag'] ?? 0,
                'hidden_flag' => $hiddenFlag ?: ($param['meta']['hidden'] ?? 0),
                'hidden_breadcrumb_flag' => $hiddenFlag ?: ($param['meta']['hiddenBreadcrumb'] ?? 0),
                'view_type' => $param['meta']['viewType']
            ];

            if (!empty($param['id'])) {
                // 更新菜单
                $updateData['update_time'] = now();
                $id = $this->dao->update($param['id'], $updateData, 'id')->id;
            } else {
                // 新建菜单

                // 菜单名称唯一
                if ($this->dao->find([['name', '=', $param['name']], ['delete_flag', '=', 0]])) exception('菜单名称已存在');

                $updateData['create_time'] = now();
                $id = $this->dao->save($updateData)->id;
            }

            event('UpdateAdminAuth', 1);

            return success(['id' => $id]);
        } catch (Exception $e) {
            return fail($e->getMessage());
        }
    }

    /**
     * 软删菜单
     * @param array $param
     */
    public function delSystemMenu(array $param = ['ids' => []])
    {
        try {
            Validate(SystemMenuValidate::class)->scene('delSystemMenu')->check($param);

            // 软删菜单
            $this->dao->update([
                ['id', 'in', $param['ids']]
            ], [
                'delete_flag' => 1,
                'delete_time' => now()
            ]);

            return success();
        } catch (Exception $e) {
            return fail($e->getMessage());
        }
    }

    /**
     * 排序菜单
     * @param array $param ['draggingNode' => '', 'dropNode' => '', 'dropType' => '']
     */
    public function sortSystemMenu(array $param)
    {
        try {
            Validate(SystemMenuValidate::class)->scene('sortSystemMenu')->check($param);

            // 释放对象的排序值
            $where[] = ['id', '=', $param['dropNode']];
            $dropNodePidSort = $this->dao->getColumn($where, ['sort', 'pid']);
            $dropNodePid = $dropNodePidSort[0]['pid'];
            $dropNodeSort = $dropNodePidSort[0]['sort'];

            switch ($param['dropType']) {
                case 'before':
                    $targetSort = $dropNodeSort + 1;
                    $updateData = [
                        'sort' => $targetSort,
                        'pid' => $dropNodePid
                    ];
                    break;
                case 'after':
                    $targetSort = $dropNodeSort - 1;
                    $updateData = [
                        'sort' => $targetSort,
                        'pid' => $dropNodePid
                    ];
                    break;
                case 'inner':
                    $updateData = [
                        'sort' => 0,
                        'pid' => $param['dropNode']
                    ];
                    break;
                default:
                    throw new Exception('未知排序');
            }

            // 更新拖拽对象排序值
            $this->dao->update(['id' => $param['draggingNode']], array_merge($updateData, ['update_time' => now()]));

            return success();
        } catch (Exception $e) {
            return fail($e->getMessage());
        }
    }
}